package demoMod.anm2editor.ui;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import demoMod.anm2editor.fonts.FontKeys;
import demoMod.anm2editor.interfaces.ReloadStringsSubscriber;
import demoMod.anm2editor.localization.LocalizedStrings;
import demoMod.anm2editor.model.Animation;
import demoMod.anm2editor.model.KeyFrame;
import demoMod.anm2editor.model.Project;
import demoMod.anm2editor.model.Track;
import demoMod.gdxform.abstracts.Container;
import demoMod.gdxform.core.FormManager;
import demoMod.gdxform.helpers.FontHelper;
import demoMod.gdxform.interfaces.Element;
import demoMod.gdxform.interfaces.KeyboardEventSubscriber;
import demoMod.gdxform.interfaces.MouseEventSubscriber;
import demoMod.gdxform.ui.GButton;
import demoMod.gdxform.ui.GCheckBox;
import demoMod.gdxform.ui.GLabel;
import demoMod.gdxform.ui.GTextField;

import java.util.List;

public class StatusBar extends Container<Element> implements MouseEventSubscriber, KeyboardEventSubscriber, ReloadStringsSubscriber {
    public static final String ID = "StatusBar";
    private boolean mouseDown = false;

    public static int getMaxAnimationLength() {
        if (Project.currentProject.getCurrentAnimation() == null) return 1;
        int max = Integer.MIN_VALUE;
        for (Track track : Project.currentProject.getTracks()) {
            int sum = 0;
            for (KeyFrame keyFrame : track.getContent(Project.currentProject.getCurrentAnimation().getName()).getKeyFrames()) {
                sum += keyFrame.delay;
            }
            if (sum > max) {
                max = sum;
            }
        }
        return max;
    }

    private void fitCapacity(int newLength) {
        if (Project.currentProject.getCurrentAnimation() == null) return;
        Timeline timeline = (Timeline) FormManager.getInstance().getContainerById(Timeline.ID);
        if (newLength > 120 && newLength > Project.currentProject.getCurrentAnimation().getAnimationLength()) {
            while (timeline.getScrollPane().getPlainWidth() < newLength * timeline.getCellWidth()) {
                timeline.getScrollPane().setPlainWidth(timeline.getScrollPane().getPlainWidth() + timeline.getCellWidth() * 50);
            }
        } else if (newLength < Project.currentProject.getCurrentAnimation().getAnimationLength() && getMaxAnimationLength() < Project.currentProject.getCurrentAnimation().getAnimationLength()) {
            timeline.getScrollPane().setPlainWidth(timeline.getCellWidth() * Math.max(120.0F, Math.max(newLength, getMaxAnimationLength())));
        }
    }

    public StatusBar() {
        setBackground(Color.TEAL.cpy());
        setHeight(20);
        setId(ID);
        LocalizedStrings.subscribe(this);

        List<String> strings = LocalizedStrings.getStrings(ID);
        GCheckBox defaultAnimation = new GCheckBox(Gdx.graphics.getWidth() * 0.03F, 0, 16, 16, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void update() {
                super.update();
                if (Project.currentProject.getCurrentAnimation() == null) return;
                if (Project.currentProject.getCurrentAnimation().isDefaultAnimation() != (getState() == 1)) {
                    setState(Project.currentProject.getCurrentAnimation().isDefaultAnimation() ? 1 : 0);
                }
            }

            @Override
            public void onClick() {
                if (Project.currentProject.getCurrentAnimation() == null) return;
                Animation currentAnimation = Project.currentProject.getCurrentAnimation();
                currentAnimation.setDefaultAnimation(getState() == 1);
                if (getState() == 1) {
                    for (Animation animation : Project.currentProject.getAnimations()) {
                        if (animation != currentAnimation) {
                            animation.setDefaultAnimation(false);
                        }
                    }
                }
            }
        };
        defaultAnimation.setText(strings.get(0));
        defaultAnimation.setId("defaultAnimation");
        addElement(defaultAnimation);
        GCheckBox loop = new GCheckBox(Gdx.graphics.getWidth() * 0.1F, 0, 16, 16, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void update() {
                super.update();
                if (Project.currentProject.getCurrentAnimation() == null) return;
                if (Project.currentProject.getCurrentAnimation().isLoop() != (getState() == 1)) {
                    setState(Project.currentProject.getCurrentAnimation().isLoop() ? 1 : 0);
                }
            }

            @Override
            public void onClick() {
                if (Project.currentProject.getCurrentAnimation() == null) return;
                Project.currentProject.getCurrentAnimation().setLoop(getState() == 1);
            }
        };
        loop.setText(strings.get(1));
        loop.setId("loop");
        if (Project.currentProject.getCurrentAnimation() != null) {
            loop.setState(Project.currentProject.getCurrentAnimation().isLoop() ? 1 : 0);
        }
        addElement(loop);

        GButton fit = new GButton(Gdx.graphics.getWidth() * 0.2F, 0, 80.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void onClick() {
                int max = getMaxAnimationLength();
                fitCapacity(max);
                if (Project.currentProject.getCurrentAnimation() != null) {
                    Project.currentProject.getCurrentAnimation().setAnimationLength(max);
                }
            }
        };
        fit.setBackground(new Color(0.16863F, 0.63529F, 0.63529F, 1.0F));
        fit.setColor(new Color(0.53333F, 0.87451F, 0.87451F, 1.0F));
        fit.setText(strings.get(2));
        fit.setId("fit");
        addElement(fit);

        GLabel lblAnimationLength = new GLabel(Gdx.graphics.getWidth() * 0.3F, FontHelper.getFont(FontKeys.SIM_HEI_14).getLineHeight() / 2.0F, 80.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14));
        lblAnimationLength.setText(strings.get(3));
        lblAnimationLength.setId("lblAnimationLength");
        addElement(lblAnimationLength);

        GTextField animationLength = new GTextField(Gdx.graphics.getWidth() * 0.3F + 80.0F, 0, 60.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public void update() {
                super.update();
                if (getText().length() == 0 || getText().length() >= 10 || Project.currentProject.getCurrentAnimation() == null) return;
                if (Project.currentProject.getCurrentAnimation().getAnimationLength() != Integer.parseInt(getText()) && FormManager.getInstance().getEventHooks().getCurrentFocusedElement() != this) {
                    setText(Integer.toString(Project.currentProject.getCurrentAnimation().getAnimationLength()));
                }
            }

            @Override
            public boolean keyDown(int keyCode) {
                if (keyCode == Input.Keys.ENTER && this.getText().length() > 0 && Project.currentProject.getCurrentAnimation() != null) {
                    FormManager.getInstance().getEventHooks().setCurrentFocusedElement(null);
                    fitCapacity(Integer.parseInt(this.getText()));
                    Project.currentProject.getCurrentAnimation().setAnimationLength(Integer.parseInt(this.getText()));
                }
                return super.keyDown(keyCode);
            }
        };
        animationLength.setId("animationLength");
        if (Project.currentProject.getCurrentAnimation() != null) {
            animationLength.setText(Integer.toString(Project.currentProject.getCurrentAnimation().getAnimationLength()));
        } else {
            animationLength.setText("0");
        }
        animationLength.setCharFilter("[0-9]");
        addElement(animationLength);

        Timeline timeline = (Timeline) FormManager.getInstance().getContainerById(Timeline.ID);
        GButton play = new GButton(Gdx.graphics.getWidth() * 0.5F, 0, 20, 20) {
            @Override
            public void onClick() {
                timeline.play();
                setColor(Color.WHITE.cpy());
            }
        };
        play.setFgTexture(new Texture("buttons/play.png"));
        GButton pause = new GButton(Gdx.graphics.getWidth() * 0.5F + 20, 0, 20, 20) {
            @Override
            public void onClick() {
                timeline.pause();
                setColor(Color.WHITE.cpy());
            }
        };
        pause.setFgTexture(new Texture("buttons/pause.png"));
        addElement(play);
        addElement(pause);

        GLabel lblFps = new GLabel(Gdx.graphics.getWidth() * 0.7F - 80.0F, FontHelper.getFont(FontKeys.SIM_HEI_14).getLineHeight() / 2.0F, 80.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14));
        lblFps.setText(strings.get(4));
        lblFps.setId("lblFps");
        GTextField fps = new GTextField(Gdx.graphics.getWidth() * 0.7F, 0, 50.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public boolean keyDown(int keyCode) {
                if (keyCode == Input.Keys.ENTER && this.getText().length() > 0 && this.getText().length() < 10) {
                    if (Integer.parseInt(this.getText()) > 60) {
                        this.setText("60");
                    }
                    Project.currentProject.setFps(Integer.parseInt(this.getText()));
                    FormManager.getInstance().getEventHooks().setCurrentFocusedElement(null);
                }
                return super.keyDown(keyCode);
            }
        };
        fps.setCharFilter("[0-9]");
        fps.setText(Integer.toString(Project.currentProject.getFps()));
        addElement(lblFps);
        addElement(fps);
        FormManager.getInstance().sortContainers();

        GLabel lblAuthor = new GLabel(Gdx.graphics.getWidth() * 0.8F - 50.0F, FontHelper.getFont(FontKeys.SIM_HEI_14).getLineHeight() / 2.0F, 50.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14));
        lblAuthor.setText(strings.get(5));
        lblAuthor.setId("lblAuthor");
        GTextField author = new GTextField(Gdx.graphics.getWidth() * 0.8F, 0, 80.0F, 20, FontHelper.getFont(FontKeys.SIM_HEI_14)) {
            @Override
            public boolean keyDown(int keyCode) {
                if (keyCode == Input.Keys.ENTER && this.getText().length() > 0) {
                    Project.currentProject.setAuthor(this.getText());
                    FormManager.getInstance().getEventHooks().setCurrentFocusedElement(null);
                }
                return super.keyDown(keyCode);
            }
        };
        author.setId("author");
        author.setText(Project.currentProject.getAuthor());
        addElement(lblAuthor);
        addElement(author);

    }

    @Override
    public float getX(boolean isAbsolute) {
        return getParent() != null ? getParent().getX(isAbsolute) : 0;
    }

    @Override
    public float getY(boolean isAbsolute) {
        return getParent() != null ? getParent().getY(isAbsolute) : 0;
    }

    @Override
    public float getWidth() {
        return getParent() != null ? getParent().getWidth() : Gdx.graphics.getWidth();
    }

    @Override
    public boolean clickDown(int screenX, int screenY, int button) {
        mouseDown = (float)screenX >= this.getX(true) && (float)screenX <= this.getX(true) + this.getWidth() && (float)(Gdx.graphics.getHeight() - screenY) >= this.getY(true) && (float)(Gdx.graphics.getHeight() - screenY) <= this.getY(true) + this.getHeight();
        if (mouseDown) {
            List<Element> elements = this.getElements();
            for(int i = elements.size() - 1; i >= 0; --i) {
                Element element = elements.get(i);
                if (element instanceof MouseEventSubscriber && ((MouseEventSubscriber)element).clickDown(screenX, screenY, button)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean clickUp(int screenX, int screenY, int button) {
        if (!this.mouseDown) return false;
        this.mouseDown = false;
        List<Element> elements = this.getElements();

        for(int i = elements.size() - 1; i >= 0; --i) {
            Element element = elements.get(i);
            if (element instanceof MouseEventSubscriber && ((MouseEventSubscriber)element).clickUp(screenX, screenY, button)) {
                break;
            }
        }
        return true;
    }

    @Override
    public boolean mouseDragged(int screenX, int screenY) {
        List<Element> elements = this.getElements();
        for(int i = elements.size() - 1; i >= 0; --i) {
            Element element = elements.get(i);
            if (element instanceof MouseEventSubscriber && ((MouseEventSubscriber)element).mouseDragged(screenX, screenY)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean mouseMoved(int i, int i1) {
        return false;
    }

    @Override
    public boolean scrolled(int i) {
        return false;
    }

    @Override
    public boolean moveToElementBorder(Element element) {
        return false;
    }

    @Override
    public boolean keyDown(int keyCode) {
        for (Element element : getElements()) {
            if (element instanceof KeyboardEventSubscriber) {
                if (((KeyboardEventSubscriber) element).keyDown(keyCode)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean keyUp(int keyCode) {
        for (Element element : getElements()) {
            if (element instanceof KeyboardEventSubscriber) {
                if (((KeyboardEventSubscriber) element).keyUp(keyCode)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean keyTyped(char key) {
        for (Element element : getElements()) {
            if (element instanceof KeyboardEventSubscriber) {
                if (((KeyboardEventSubscriber) element).keyTyped(key)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public int getPriority() {
        return Integer.MIN_VALUE + 1;
    }

    @Override
    public void onReloadStrings() {
        List<String> strings = LocalizedStrings.getStrings(ID);
        GCheckBox defaultAnimation = (GCheckBox) getElementById("defaultAnimation");
        defaultAnimation.setText(strings.get(0));
        GCheckBox loop = (GCheckBox) getElementById("loop");
        loop.setText(strings.get(1));
        GButton fit = (GButton) getElementById("fit");
        fit.setText(strings.get(2));
        GLabel lblAnimationLength = (GLabel) getElementById("lblAnimationLength");
        lblAnimationLength.setText(strings.get(3));
        GLabel lblFps = (GLabel) getElementById("lblFps");
        lblFps.setText(strings.get(4));
        GLabel lblAuthor = (GLabel) getElementById("lblAuthor");
        lblAuthor.setText(strings.get(5));
    }
}
